﻿using System;
using System.Linq.Expressions;

namespace OpenCompiler.CodeGen
{
	public enum Visibility
	{
		Public = 1,
		Private
	}


	public interface ITypeBuilder<T> : ITypeBuilder
		where T : class
	{
		new ITypeBuilder<T> Implement<I>() where I : class;
		new ITypeBuilder<T> InheritFrom<C>() where C : class;
		new ITypeBuilder<T> ComplementWith<P>() where P : new();
		new ITypeBuilder<T> WithName(string name);
		new ITypeBuilder<T> VisibleTo(Visibility visibility);

		IMethodBuilder<T> Method(Expression<Action<T>> method);
		IMethodBuilder<T, Expression<Action<T, T1>>> Method<T1>(Expression<Action<T, T1>> method);
		IMethodBuilder<T, Expression<Action<T, T1, T2>>> Method<T1, T2>(Expression<Action<T, T1, T2>> method);
		IMethodBuilder<T, Expression<Action<T, T1, T2, T3>>> Method<T1, T2, T3>(Expression<Action<T, T1, T2, T3>> method);

		IMethodBuilder<T, Expression<Func<T, TResult>>> Method<TResult>(Expression<Func<T, TResult>> method);
		IMethodBuilder<T, Expression<Func<T, T1, TResult>>> Method<T1, TResult>(Expression<Func<T, T1, TResult>> method);
		IMethodBuilder<T, Expression<Func<T, T1, T2, TResult>>> Method<T1, T2, TResult>(Expression<Func<T, T1, T2, TResult>> method);
		IMethodBuilder<T, Expression<Func<T, T1, T2, T3, TResult>>> Method<T1, T2, T3, TResult>(Expression<Func<T, T1, T2, T3, TResult>> method);

		//IPropertyBuilder<T, TResult> Property<TResult>(Expression<Func<T, TResult>> property);
	}

	public interface ITypeBuilder
	{
		ITypeBuilder Implement<I>() where I : class;
		ITypeBuilder InheritFrom<C>() where C : class;
		ITypeBuilder ComplementWith<P>() where P : new();
		ITypeBuilder WithName(string name);
		ITypeBuilder Implement(Type interfaceType);
		ITypeBuilder ComplementWith(Type complementingType);
		ITypeBuilder VisibleTo(Visibility visibility);

		IMethodBuilder Method(string name);
		IMethodBuilder<Expression<Func<TResult>>> Method<TResult>(Expression<Func<TResult>> method);

		IPropertyBuilder Property(string name);

		string Name { get; }
		Visibility Visibility { get; }
		IInterface[] Interfaces { get; }

		IMethodBuilder[] Methods { get; }
		IPropertyBuilder[] Properties { get; }
	}
}
